package com.liyu.iblog.web;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

import com.liyu.iblog.domain.Blog;
import com.liyu.iblog.domain.Category;
import com.liyu.iblog.enums.PaginationType;
import com.liyu.iblog.service.BlogService;
import com.liyu.iblog.service.CategoryService;
import com.liyu.iblog.service.CommentService;

@Controller
@RequestMapping("/admin")
@SessionAttributes("blog")
public class AdminController {

    public static final Logger logger = LoggerFactory.getLogger(AdminController.class);
    
    private BlogService blogService;
    private CategoryService categoryService;
    private CommentService commentService;
    
    @Autowired
    public AdminController(BlogService blogService, CategoryService categoryService,
            CommentService commentService) {
        this.blogService = blogService;
        this.categoryService = categoryService;
        this.commentService = commentService;
    }
    
    @RequestMapping(method = RequestMethod.GET)
    public String loadAdminPage() {
        return "admin/admin";
    }
    
    @RequestMapping(value="/blogs", method = RequestMethod.GET)
    public String loadBlogsPage(
            @RequestParam(required = false) Integer pageNum,
            Model model) {
        
        //if page number not set, point to first page
        if (pageNum == null || pageNum < 1) 
            pageNum = 1;

        model.addAttribute("pageNum", pageNum);
        
        List<Blog> blogs = blogService.getBolgsWithTimeDescOrder(
                (pageNum - 1) * BlogService.BLOG_PAGINATION_SIZE,
                BlogService.BLOG_PAGINATION_SIZE);
        model.addAttribute("blogs", blogs);
        
        if (pageNum > 1) {
            model.addAttribute("hasPrePage", true);
            model.addAttribute("prePageNum", pageNum - 1);
        }
        
        //if current page is full assume next page is available
        if (blogs != null && blogs.size() == BlogService.BLOG_PAGINATION_SIZE) {
            model.addAttribute("hasNextPage", true);
            model.addAttribute("nextPageNum", pageNum + 1);
        }
        
        model.addAttribute(PaginationType.ADMIN_STYLE.toString(), true);
        
        return "admin/blogList";
    }
    
    @RequestMapping(value="/blogs/new", method = RequestMethod.GET)
    public String loadBlogCreationPage(Model model) {
        logger.debug("setup blog form...");
        List<Category> categories = categoryService.getAllCategories();
        model.addAttribute("blog", new Blog());
        model.addAttribute("categories", categories);
        return "admin/blogNew";
    }
    
    @RequestMapping(value="/blogs/new", method = RequestMethod.POST)
    public String handleCreateBlog (
            @ModelAttribute("blog") Blog blog,
            BindingResult result,
            SessionStatus status,
            Model model) {
        logger.debug("handling blog <" + blog.getTitle() +  "> creation request...");
        blogService.create(blog);
        return "redirect:/admin/blogs";
    }
    
    @RequestMapping(value="/blogs/view/{id}", method=RequestMethod.GET)
    public String loadBlogViewPage(
            @PathVariable String id,
            Model model) {
        Blog blog = blogService.getBlogWithComment(id);
        model.addAttribute("blog", blog);
        return "admin/blogView";
    }
    
    @RequestMapping(value="/blogs/edit/{id}", method=RequestMethod.GET)
    public String loadBlogEditPage(
            @PathVariable String id,
            Model model) {
        Blog blog = blogService.getBlogById(id);
        model.addAttribute("blog", blog);
        List<Category> categories = categoryService.getAllCategories();
        model.addAttribute("categories", categories);
        return "admin/blogEdit";
    }
    
    @RequestMapping(value="/blogs/edit/{id}", method=RequestMethod.POST)
    public String handleBlogEditRequest(
            @PathVariable String id,
            @ModelAttribute("blog") Blog newBlog,
            BindingResult result,
            SessionStatus status,
            Model model) {
        logger.debug("handling blog edit request...");
        blogService.updateBlog(id, newBlog);
        return "redirect:/admin/blogs";
    }
    
    @RequestMapping(value="/blogs/delete/{id}", method = RequestMethod.DELETE)
    public @ResponseBody String handleBlogDeleteRequest(
            @PathVariable String id) {
        logger.debug("handling blog deletion request...");
        blogService.deleteBlog(id);
        return "success";
    }
    
    @RequestMapping(value="/categories", method = RequestMethod.GET)
    public String loadCategoryPage(Model model) {
        logger.debug("loading category page...");
        List<Category> categories = categoryService.getAllCategories();
        model.addAttribute("categories", categories);
        return "admin/categoryList";
    }
    
    @RequestMapping(value="/categories", method = RequestMethod.POST)
    public @ResponseBody String createCategory(@RequestBody String categoryName) {
        logger.debug("handling category creation... for category :" + categoryName);
        Category category = new Category();
        category.setName(categoryName);
        categoryService.saveCategory(category);
        return category.getId();
    }
    
    @RequestMapping(value="categories/{id}", method = RequestMethod.DELETE)
    public @ResponseBody String deleteCategory(
            @PathVariable("id") String id) {
        logger.debug("handling category deletion...<" + id + ">");
        categoryService.deleteCategory(id);
        return "success";
    }
    
    @RequestMapping(value="comments/{encodedKey}", method = RequestMethod.DELETE)
    public @ResponseBody String deleteComment(
            @PathVariable String encodedKey) {
        commentService.removeCommentByEncodedKey(encodedKey);
        return "success";
    }
}
